//
//  LJJCycleCollectionView.swift
//  LJJCycleDemo
//
//  Created by liujunjie on 2019/1/29.
//  Copyright © 2019 junjie.liu. All rights reserved.
//

import UIKit
import SDWebImage

typealias BackPageControl = (UIControl) -> ()

typealias ClickItemOperationBlock = (NSInteger) -> ()

fileprivate extension CGSize {
    static let kCycleScrollViewInitialPageControlDotSize = CGSize(width: 10, height: 10)
}

/** 分页控件位置枚举 */
enum LJJCycleScrollViewPageContolAliment : Int {
    case right
    case center
}

/** 样式 */
enum LJJCycleScrollViewPageContolStyle : Int {
    case classic // 系统自带经典样式
    case animated // 动画效果pagecontrol //暂时没有作用
    case none // 不显示pagecontrol
}

//MARK: --对外暴露接口信息
extension LJJCycleCollectionView {
    
    /** 数据源*/
    func setImageSource(_ imageSource: Array<Any>) {
        _imageSource = imageSource
        
        /**当不是无限循环的时候 不用乘以个数*/
        if _infiniteLoop !=  true {
            _totalItemsCount = _imageSource.count
        }else{
            _totalItemsCount = (_imageSource.count) * 1000
        }
        
        /**当数据源大于1个时候 开启轮播 否则禁止滚动销毁时间戳*/
        if _imageSource.count > 1 {
            self.isScrollEnabled = true
            self.setAutoScroll(_autoScroll)
        }else{
            self.isScrollEnabled = false
            self.invalidateTimer()
        }
        self.setupPageControl()
        self.reloadData()
    }
    
    /**标题 数据源*/
    func setTitlesGroup(_ titleArray: Array<String>) {
        _titleArray = titleArray
        if _onlyDisplayText == true {
            var temp : Array<String> = []
            for _ in 0..<_titleArray.count {
                temp.append("")
            }
            self.backgroundColor = UIColor.clear
            self._imageSource = temp
        }
    }
    
    /**是否只展示 文字轮播 默认false*/
    func setonlyDisplayText(_ onlyDisplayText: Bool) {
        _onlyDisplayText = onlyDisplayText
    }
    
    /**是否自动滚动*/
    func setAutoScroll(_ autoScroll: Bool) {
        _autoScroll = autoScroll
        self.invalidateTimer()
        self.setupTimer()
    }
    
    /**自动滚动间隔时间 默认2秒*/
    func setAutoScrollTimeInterval(_ autoScrollTimeInterval: Double) {
        _autoScrollTimeInterval = autoScrollTimeInterval
        setAutoScroll(_autoScroll)
    }
    
    /** 设定滚动方向*/
    func setScrollDirection(_ scrollDirection: UICollectionView.ScrollDirection) {
        _scrollDirection = scrollDirection
        _flowLayout?.scrollDirection = _scrollDirection
    }
    
    /** 是否无限循环,默认Yes */
    func setInfiniteLoop(_ infiniteLoop: Bool) {
        _infiniteLoop = infiniteLoop
        setImageSource(_imageSource)
    }
    
    /** 可以调用此方法手动控制滚动到哪一个index */
    func makeScrollViewScrollToIndex(_ index: NSInteger) {
        if _autoScroll {self.invalidateTimer()}
        if (0 == _totalItemsCount) {return}
        self.scrollToIndex(Int(_totalItemsCount) * Int(0.5) + index)
        if _autoScroll {self.setupTimer()}
    }
    
    /** 可以调用此方法手动控制滚动到哪一个index */
    func setplaceholderImage(_ image: UIImage) {
        _placeholderImage = image
        let bgImageView = UIImageView()
        bgImageView.contentMode = UIView.ContentMode.scaleAspectFit
        insertSubview(bgImageView, belowSubview: self)
        _backgroundImageView = bgImageView
    }
    
    /** pagecontrol 样式 */
    func setpageControlStyle(_ style: LJJCycleScrollViewPageContolStyle) {
        _pageControlStyle = style
        self.setupPageControl()
    }
    
    /** 设分页圆点的颜色
     currentPageDotColor: 当前分页控件小圆标颜色 默认白色
     pageDotColor: 其他分页控件小圆标颜色 默认灰色
     */
    func setPageControlColor(_ currentPageDotColor: UIColor = UIColor.white, _ pageDotColor: UIColor = UIColor.lightGray) {
        _currentPageDotColor = currentPageDotColor
        _pageDotColor = pageDotColor
        let pageContol = _pageControl as! UIPageControl
        pageContol.currentPageIndicatorTintColor = currentPageDotColor
        pageContol.pageIndicatorTintColor = pageDotColor
    }
    
    /** 设分页圆点的大小*/
    func setPageControlDotSize(_ cgSize: CGSize = .kCycleScrollViewInitialPageControlDotSize) {
        _pageControlDotSize = cgSize
        self.setupPageControl()
    }
    
    /**滚动手势禁用（文字轮播较实用 */
    func disableScrollGesture() {
        self.canCancelContentTouches = false
        for gesture: UIGestureRecognizer? in self.gestureRecognizers ?? [] {
            if (gesture is UIPanGestureRecognizer) {
                if let gesture = gesture {
                    self.removeGestureRecognizer(gesture)
                }
            }
        }
    }
    
    /*获取父视图Frame*/
    func getSuperViewFrame(_ view: UIView ) {
        _superView = view
    }
    
    /*
     轮播文字label背景颜色
     轮播文字label高度
     轮播文字label对齐方式
     轮播文字label字体颜色
     轮播文字label字体大小
     */
    func setRotationtextConfig(_ titleLabelBackgroundColor:UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5),
                               _ titleLabelHeight:CGFloat = 30,
                               _ titleLabelTextAlignment: NSTextAlignment = .left,
                               _ titleLabelTextColor:UIColor = UIColor.white,
                               _ titleLabelTextFont:UIFont = UIFont.systemFont(ofSize: 14)) {
        _titleLabelBackgroundColor = titleLabelBackgroundColor
        _titleLabelHeight = titleLabelHeight
        _titleLabelTextAlignment = titleLabelTextAlignment
        _titleLabelTextColor = titleLabelTextColor
        _titleLabelTextFont = titleLabelTextFont
    }
}

class LJJCycleCollectionView: UICollectionView {
    
    var clickItemOperationBlock: ClickItemOperationBlock?
    
    /** 数据源*/
    fileprivate var _imageSource: Array<Any> = []
    /** 标题数据源*/
    fileprivate var _titleArray: Array<String> = []
    /**数据个数*/
    fileprivate var _totalItemsCount: NSInteger = 0
    /**是否自动滚动*/
    fileprivate var _autoScroll: Bool = true
    /**是否 只展示文字轮播*/
    fileprivate var _onlyDisplayText: Bool = false
    /**定时器*/
    fileprivate var _timer: Timer?
    /**自动滚动间隔时间,默认5s*/
    fileprivate var _autoScrollTimeInterval: Double = 5
    /**父视图ViewFrame*/
    fileprivate var _fatherFrame: CGRect = .zero
    /**UICollectionViewFlowLayout*/
    fileprivate var _flowLayout: UICollectionViewFlowLayout?
    /** 是否无限循环,默认Yes */
    fileprivate var _infiniteLoop: Bool = true
    /*垫图*/
    fileprivate var _placeholderImage: UIImage = UIImage(named: "placeholder")!
    /** 图片滚动方向，默认为水平滚动 */
    fileprivate var _scrollDirection : UICollectionView.ScrollDirection = .horizontal
    
    /**分页管理器*/
    fileprivate var _pageControl: UIControl?
    /** pagecontrol 样式，默认为经典样式 */
    fileprivate var _pageControlStyle: LJJCycleScrollViewPageContolStyle = .classic
    /** 分页控件位置 */
    fileprivate var _pageControlAliment: LJJCycleScrollViewPageContolAliment = .center
    /** 当前分页控件小圆标颜色 默认白色*/
    fileprivate var _currentPageDotColor: UIColor = UIColor.white
    /** 其他分页控件小圆标颜色 默认灰色*/
    fileprivate var _pageDotColor: UIColor = UIColor.lightGray
    /** 分页控件小圆标大小 */
    fileprivate var _pageControlDotSize: CGSize = .kCycleScrollViewInitialPageControlDotSize
    /** 当前分页控件小圆标图片 */
    fileprivate var _currentPageDotImage: UIImage = UIImage(named: "pageControlCurrentDot")!
    /** 其他分页控件小圆标图片 */
    fileprivate var _pageDotImage: UIImage = UIImage(named: "pageControlDot")!
    /** 分页控件距离轮播图的底部间距（在默认间距基础上）的偏移量 */
    fileprivate var _pageControlBottomOffset: CGFloat = 0
    /** 分页控件距离轮播图的右边间距（在默认间距基础上）的偏移量 */
    fileprivate var _pageControlRightOffset: CGFloat = 0
    /** 背景图片*/
    fileprivate var _backgroundImageView: UIImageView?
    var backPageControl : BackPageControl?
    
    /*获取父视图*/
    fileprivate var _superView: UIView = UIView()
    
    ////////轮播文字设置/////////
    /** 轮播文字label背景颜色 */
    fileprivate var _titleLabelBackgroundColor : UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
    /** 轮播文字label高度 */
    fileprivate var _titleLabelHeight : CGFloat = 30
    /** 轮播文字label对齐方式 */
    fileprivate var _titleLabelTextAlignment: NSTextAlignment = .left
    /** 轮播文字label字体颜色 */
    fileprivate var _titleLabelTextColor: UIColor = UIColor.white
    /** 轮播文字label字体大小 */
    fileprivate var _titleLabelTextFont: UIFont = UIFont.systemFont(ofSize: 14)
    
    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        _flowLayout = layout as? UICollectionViewFlowLayout
        self.config()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

//MARK: --基础配置信息
extension LJJCycleCollectionView {
    
    fileprivate  func config() {
        self.backgroundColor = UIColor.clear
        self.isPagingEnabled = true
        self.showsHorizontalScrollIndicator = false
        self.showsVerticalScrollIndicator = false
        self.register(LJJCollectionViewCell.classForCoder(), forCellWithReuseIdentifier: LJJCollectionViewCell.description())
        self.delegate = self
        self.dataSource = self
        self.scrollsToTop = false
    }
}

//MARK: -- UICollectionViewDataSource
extension LJJCycleCollectionView: UICollectionViewDelegate, UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return _totalItemsCount
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell : LJJCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: LJJCollectionViewCell.description(), for: indexPath) as! LJJCollectionViewCell
        let itemIndex: Int = self.pageControlIndexWithCurrentCellIndex(indexPath.item)
        let image = _imageSource[itemIndex]
        cellImageView(cell, image as Any, itemIndex)
        
        if cell.hasConfigured == nil {
            cell.titleLabelBackgroundColor = _titleLabelBackgroundColor
            cell.titleLabelHeight = _titleLabelHeight
            cell.titleLabelTextAlignment = _titleLabelTextAlignment
            cell.titleLabelTextColor = _titleLabelTextColor
            cell.titleLabelTextFont = _titleLabelTextFont
            cell.hasConfigured = true
            cell.imageView?.contentMode = .scaleToFill
            cell.clipsToBounds = true
            cell.onlyDisplayText = _onlyDisplayText
        }
        return cell
    }
    
    //处理传过来的数据到底是网址还是字符串类型的UIImage
    func cellImageView(_ cell: LJJCollectionViewCell, _ image: Any , _ itrmIndex: Int) {
        
        if !self._onlyDisplayText && (image is String) {
            
            if (image as! String).hasPrefix("http") {
                cell.imageView?.sd_setImage(with: URL(string: image as! String), placeholderImage: _placeholderImage)
            }else{
                var images: UIImage = UIImage(named: image as! String) ?? UIImage()
                if images == UIImage() {
                    images = UIImage(contentsOfFile: image as! String) ?? UIImage()
                }
                cell.imageView?.image = images
            }
        }else if !self._onlyDisplayText && (image is UIImage) {
            cell.imageView?.image = image as? UIImage
        }
        
        if _titleArray.count > 0 && itrmIndex < _titleArray.count {
            cell.title = _titleArray[itrmIndex]
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        guard clickItemOperationBlock != nil else {
            return
        }
        clickItemOperationBlock!(pageControlIndexWithCurrentCellIndex(indexPath.item))
    }
}

//MARK: -- UIScrollViewDelegate + 视图滚动
extension LJJCycleCollectionView: UIScrollViewDelegate {
    
    /**scrollview滚动过程中，自动调用的方法（惯性滚动也会调用)*/
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
        guard self._imageSource.count > 0 else {return}
        let itemIndex = self.currentIndex()
        let indexOnPageControl = self.pageControlIndexWithCurrentCellIndex(itemIndex)
        let pageControl = _pageControl as? UIPageControl
        pageControl?.currentPage = indexOnPageControl
    }
    
    /** scrollview 将要滚动的时候调用*/
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        if _autoScroll {
            self.invalidateTimer()
        }
    }
    
    /** scrollview 已经停止滚动时，调用*/
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if _autoScroll {
            self.setupTimer()
        }
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        scrollViewDidEndScrollingAnimation(self)
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        guard self._imageSource.count > 0 else {return}
        let itemIndex = self.currentIndex()
        let _ = self.pageControlIndexWithCurrentCellIndex(itemIndex)
    }
    
    //视图滚动
    func scrollToIndex(_ targetIndex: Int) {
        if targetIndex >= _totalItemsCount {
            if _infiniteLoop {
                self.scrollToItem(at: NSIndexPath(item: _totalItemsCount * Int(0.5), section: 0) as IndexPath, at:[],  animated: true)
            }
            return
        }
        self.scrollToItem(at: NSIndexPath(item: targetIndex, section: 0) as IndexPath, at:[],  animated: true)
    }
}

//MARK: -- 分页控制器
extension LJJCycleCollectionView {
    
    fileprivate func setupPageControl() {
        
        if (_pageControl != nil) {_pageControl?.reloadInputViews()}
        if (_imageSource.count <= 1) {_pageControl?.isHidden = true} /**当只有一张图片的时候,隐藏_pageControl*/
        let indexOnPageControl = self.pageControlIndexWithCurrentCellIndex(self.currentIndex())
        switch _pageControlStyle {
        case .animated:
            let pageControl = UIPageControl()
            pageControl.numberOfPages = _imageSource.count
            pageControl.currentPageIndicatorTintColor = _currentPageDotColor
            pageControl.pageIndicatorTintColor = _pageDotColor
            pageControl.isUserInteractionEnabled = false
            pageControl.currentPage = indexOnPageControl
            self.addSubview(pageControl)
            _pageControl = pageControl
            break
        case .classic:
            let pageControl = UIPageControl()
            pageControl.numberOfPages = _imageSource.count
            pageControl.currentPageIndicatorTintColor = _currentPageDotColor
            pageControl.pageIndicatorTintColor = _pageDotColor
            pageControl.isUserInteractionEnabled = false
            pageControl.currentPage = indexOnPageControl
            self.addSubview(pageControl)
            _pageControl = pageControl
            break
        default: break
        }
        
    }
}

//MARK: --定时器处理
extension LJJCycleCollectionView {
    
    /**定时器创建*/
    fileprivate func setupTimer() {
        /**创建定时器前先停止定时器，不然会出现僵尸定时器，导致轮播频率错误*/
        self.invalidateTimer()
        
        /**只有需要自动播放时 才会开启定时器*/
        guard _autoScroll else {return}
        
        /**只有当数据大于2个的时候需要自动播放 才会开启定时器*/
        guard _totalItemsCount > 1  else {
            return
        }
        let timer = Timer(timeInterval: _autoScrollTimeInterval, target: self, selector: #selector(self.automaticScroll), userInfo: nil, repeats: true)
        _timer = timer
        RunLoop.main.add(timer, forMode: .common)
    }
    
    /**定时器销毁*/
    func invalidateTimer() {
        _timer?.invalidate()
        _timer = nil
    }
    
    @objc func automaticScroll() {
        let currentIndex = self.currentIndex()
        let targetIndex = currentIndex + 1
        scrollToIndex(targetIndex)
    }
}

//MARK: -- 重新计算
extension LJJCycleCollectionView {
    
    //计算下标
    fileprivate func pageControlIndexWithCurrentCellIndex(_ index: NSInteger) -> Int {
        return index % (_imageSource.count)
    }
    
    //计算偏移量
    fileprivate func currentIndex() -> Int {
        if self.ljj_width == 0 || self.ljj_height == 0 {
            return 0
        }
        var index = 0
        if _flowLayout?.scrollDirection == UICollectionView.ScrollDirection.horizontal {
            index = Int((self.contentOffset.x + (_flowLayout?.itemSize.width)! * 0.5 ) / (_flowLayout?.itemSize.width)!)
        }else{
            index = Int((self.contentOffset.y + (_flowLayout?.itemSize.height)! * 0.5 ) / (_flowLayout?.itemSize.height)!)
        }
        return max(0, index)
    }
}

//MARK: -- 重布局
extension LJJCycleCollectionView {
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        if self.contentOffset.x == 0 && _flowLayout?.scrollDirection == UICollectionView.ScrollDirection.horizontal {
            var targetIndex : Int = 0
            if _infiniteLoop {
                targetIndex = Int(CGFloat(_totalItemsCount) * 0.5)
            }else{
                targetIndex = 0
            }
            self.scrollToItem(at: IndexPath(item: targetIndex, section: 0), at: [], animated: false)
        }
        
        if self.contentOffset.y == 0 && _flowLayout?.scrollDirection == UICollectionView.ScrollDirection.vertical {
            var targetIndex : Int = 0
            if _infiniteLoop {
                targetIndex = Int(CGFloat(_totalItemsCount) * 0.5)
            }else{
                targetIndex = 0
            }
            self.scrollToItem(at: IndexPath(item: targetIndex, section: 0), at: [], animated: false)
        }
        
        var size: CGSize = .zero
        size = CGSize(width: CGFloat(_imageSource.count) * _pageControlDotSize.width * 1.5, height: _pageControlDotSize.height)
        
        var x = (_superView.frame.size.width - size.width) * 0.5
        if _pageControlAliment == .right {
            x = self.ljj_width - size.width - 10
        }
        let y = self.ljj_height - size.height - 10
        
        var pageControlFrame = CGRect(x: x, y: y, width: size.width, height: size.height)
        pageControlFrame.origin.y -= _pageControlBottomOffset
        pageControlFrame.origin.x -= _pageControlRightOffset
        _pageControl!.frame = pageControlFrame
        if _backgroundImageView != nil {
            _backgroundImageView?.frame = self.bounds
        }
        guard backPageControl != nil else {return}
        backPageControl!(_pageControl!)
    }
}

//MARK: -- 视图销毁
extension LJJCycleCollectionView {
    
    override func willMove(toSuperview newSuperview: UIView?) {
        if (newSuperview == nil) {
            self.invalidateTimer()
        }
    }
}

